/**
  * Author: Mei
  * Date: 2021-01-10 14:11
  * Description: 
  *
  */
#include "../head.h"
#include "any.h"
#include "lambda_to_function.cpp"
#include "NonCopyable.cpp"

class MessageBus : NonCopyable {
public:
    //注册消息
    template<typename F>
    void Attach(F &&f, const string &strTopic = "") {
        auto func = to_function(forward<F>(f));
        Add(strTopic, move(func));
    }

    //发送消息
    //不带参数
    template<typename R>
    void SendReq(const string &strTopic = "") {
        using function_type = function<R()>;
        string strMsgType = strTopic + typeid(function_type).name();
        auto range = m_map.equal_range(strMsgType); //返回pair pair中的first为符合的begin second为end
        for (Iterator it = range.first; it != range.second; ++it) {
            auto f = it->second.AnyCast<function_type>();
            f();
        }
    }

    //带参数
    template<typename R, typename ...Args>
    void SendReq(Args ...args, const string &strTopic = "") {
        using function_type = function<R(Args...)>;
        string strMsgType = strTopic + typeid(function_type).name();
        auto range = m_map.equal_range(strMsgType); //返回pair pair中的first为符合的begin second为end
        for (Iterator it = range.first; it != range.second; ++it) {
            auto f = it->second.AnyCast<function_type>();
            f(forward<Args>(args)...);
        }
    }

    //移除某个主题，需要主题和消息类型
    template<typename R, typename ...Args>
    void Remove(const string &strTopic = "") {
        using function_type = function<R(Args...)>;
        string strMsgType = strTopic + typeid(function_type).name();
        int count = m_map.count(strMsgType);
        auto range = m_map.equal_range(strMsgType); //返回pair pair中的first为符合的begin second为end
        m_map.erase(range.first, range.second);
    }

private:
    template<typename F>
    void Add(const string &strTopic, F &&f) {
        string messageType = strTopic + typeid(F).name();
        m_map.emplace(move(messageType), forward<F>(f));
    }

private:
    multimap<string, Any> m_map;
    typedef multimap<string, Any>::iterator Iterator;
};

//测试
int main2() {
    MessageBus bus;
    //注册消息
    bus.Attach([](int a) {
        cout << "no reference " << a << endl;
    });
    bus.Attach([](int &a) {
        cout << "lvalue reference " << a << endl;
    });
    bus.Attach([](int &&a) {
        cout << "rvalue reference " << a << endl;
    });
    bus.Attach([](int a) {
        cout << "no reference has return value and key " << a << endl;
        return a;
    }, "a");

    int i = 2;
    //发送消息
    bus.SendReq<void, int>(2);
    bus.SendReq<int, int>(2, "a");
    bus.SendReq<void, int&>(i);
    bus.SendReq<void, int&&>(2);

    //移除消息
    bus.Remove<void, int>();
    bus.Remove<int, int>("a");
    bus.Remove<void, int&&>();

    //再发送
    bus.SendReq<void, int>(2);
    bus.SendReq<int, int>(2, "a");
    bus.SendReq<void, int&>(i);
    bus.SendReq<void, int&&>(2);

    return 0;
}